Bug 659602 - Provide an abstraction for the platform's use of modifier keys
authorMichael Natterer <mitch@lanedo.com>
Tue, 27 Sep 2011 07:50:34 +0000 (09:50 +0200)
committerMichael Natterer <mitch@gimp.org>
Tue, 27 Sep 2011 07:56:25 +0000 (09:56 +0200)
Add enum GdkModifierIntent which identifies use cases for modifier masks
and GdkKeyMap::get_modifier_mask(). Add a default implementation which returns
what is currently hardcoded all over GTK+, and an implementation in the
quartz backend. Also add gtk_widget_get_modifier_mask() which simplifies
things by doing widget->display->keymap->get_modifier_mask().

gdk/gdkkeys.c
gdk/gdkkeys.h
gdk/gdkkeysprivate.h
gdk/gdktypes.h
gdk/quartz/gdkkeys-quartz.c
gtk/gtkwidget.c
gtk/gtkwidget.h

index f52de39e044f2bf8738c35e9a120a752e212bcd6..d2b7b61f6e5c46339a8c41a065927aeed30a3cec 100644 (file)
@@ -108,6 +108,11 @@ enum {
   LAST_SIGNAL
 };
 
+
+static GdkModifierType gdk_keymap_real_get_modifier_mask (GdkKeymap         *keymap,
+                                                          GdkModifierIntent  intent);
+
+
 static guint signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE (GdkKeymap, gdk_keymap, G_TYPE_OBJECT)
@@ -117,6 +122,8 @@ gdk_keymap_class_init (GdkKeymapClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  klass->get_modifier_mask = gdk_keymap_real_get_modifier_mask;
+
   /**
    * GdkKeymap::direction-changed:
    * @keymap: the object on which the signal is emitted
@@ -605,6 +612,61 @@ gdk_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
   return GDK_KEYMAP_GET_CLASS(keymap)->map_virtual_modifiers (keymap, state);
 }
 
+static GdkModifierType
+gdk_keymap_real_get_modifier_mask (GdkKeymap         *keymap,
+                                   GdkModifierIntent  intent)
+{
+  switch (intent)
+    {
+    case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
+      return GDK_CONTROL_MASK;
+
+    case GDK_MODIFIER_INTENT_CONTEXT_MENU:
+      return 0;
+
+    case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
+      return GDK_SHIFT_MASK;
+
+    case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
+      return GDK_CONTROL_MASK;
+
+    case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
+      return GDK_MOD1_MASK | GDK_CONTROL_MASK;
+
+    default:
+      g_return_val_if_reached (0);
+    }
+}
+
+/**
+ * gdk_keymap_get_modifier_mask:
+ * @keymap: a #GdkKeymap
+ * @intent: the use case for the modifier mask
+ *
+ * Returns the modifier mask the @keymap's windowing system backend
+ * uses for a particular purpose.
+ *
+ * Note that this function always returns real hardware modifiers, not
+ * virtual ones (e.g. it will return #GDK_MOD1_MASK rather than
+ * #GDK_META_MASK if the backend maps MOD1 to META), so there are use
+ * cases where the return value of this function has to be transformed
+ * by gdk_keymap_add_virtual_modifiers() in order to contain the
+ * expected result.
+ *
+ * Returns: the modifier mask used for @intent.
+ *
+ * Since: 3.4
+ **/
+GdkModifierType
+gdk_keymap_get_modifier_mask (GdkKeymap         *keymap,
+                              GdkModifierIntent  intent)
+{
+  g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
+
+  return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_mask (keymap, intent);
+}
+
+
 /**
  * gdk_keyval_name:
  * @keyval: a key value
index 96e360f1ea42de73df75801cb5f22bac5100bc31..b085d246ca463be3ab050ea616abccca3dfeb164 100644 (file)
@@ -114,6 +114,9 @@ void           gdk_keymap_add_virtual_modifiers    (GdkKeymap           *keymap,
                                                     GdkModifierType     *state);
 gboolean       gdk_keymap_map_virtual_modifiers    (GdkKeymap           *keymap,
                                                     GdkModifierType     *state);
+GdkModifierType gdk_keymap_get_modifier_mask       (GdkKeymap           *keymap,
+                                                    GdkModifierIntent    intent);
+
 
 /* Key values
  */
index c0f1f0eaa9698812bac16abef039e4467663204c..be1be41d03a094192b7a3fa4e13b3337bc22394a 100644 (file)
@@ -61,6 +61,8 @@ struct _GdkKeymapClass
                                          GdkModifierType *state);
   gboolean (* map_virtual_modifiers)    (GdkKeymap       *keymap,
                                          GdkModifierType *state);
+  GdkModifierType (*get_modifier_mask)  (GdkKeymap         *keymap,
+                                         GdkModifierIntent  intent);
 
 
   /* Signals */
index 87ac3b24919decb9afcd7b14413ffdf7e9a1707f..a0ea89368d497434e58183a9b59fbad18fb354aa 100644 (file)
@@ -242,6 +242,41 @@ typedef enum
   GDK_MODIFIER_MASK = 0x5c001fff
 } GdkModifierType;
 
+/**
+ * GdkModifierIntent:
+ * @GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR: the primary modifier used to invoke
+ *  menu accelerators.
+ * @GDK_MODIFIER_INTENT_CONTEXT_MENU: the modifier used to invoke context menus.
+ *  Note that mouse button 3 always triggers context menus. When this modifier
+ *  is not 0, it <strong>additionally</strong> triggers context menus when used
+ *  with mouse button 1.
+ * @GDK_MODIFIER_INTENT_EXTEND_SELECTION: the modifier used to extend selections
+ *  using &lt;modifier&gt;-click or &lt;modifier&gt;-cursor-key
+ * @GDK_MODIFIER_INTENT_MODIFY_SELECTION: the modifier used to modify selections,
+ *  which in most cases means toggling the clicked item into or out of the selection.
+ * @GDK_MODIFIER_INTENT_NO_TEXT_INPUT: when any of these modifiers is pressed, the
+ *  key event cannot produce a symbol directly. This is meant to be used for
+ *  input methods, and for use cases like typeahead search.
+ *
+ * This enum is used with gdk_keymap_get_modifier_mask() and
+ * gdk_get_modifier_mask() in order to determine what modifiers the
+ * currently used windowing system backend uses for particular
+ * purposes. For example, on X11/Windows, the Control key is used for
+ * invoking menu shortcuts (accelerators), whereas on Apple computers
+ * it's the Command key (which correspond to %GDK_CONTROL_MASK and
+ * %GDK_MOD2_MASK, respectively).
+ *
+ * Since: 3.4
+ **/
+typedef enum
+{
+  GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR,
+  GDK_MODIFIER_INTENT_CONTEXT_MENU,
+  GDK_MODIFIER_INTENT_EXTEND_SELECTION,
+  GDK_MODIFIER_INTENT_MODIFY_SELECTION,
+  GDK_MODIFIER_INTENT_NO_TEXT_INPUT
+} GdkModifierIntent;
+
 typedef enum
 {
   GDK_OK          = 0,
index 9c925ae14c659cf088285bd8fd41330a431c278c..2b9307f86834ff0f57a824ff733d0a70ca15658e 100644 (file)
@@ -746,6 +746,32 @@ gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
   return TRUE;
 }
 
+static GdkModifierType
+gdk_quartz_keymap_get_modifier_mask (GdkKeymap         *keymap,
+                                     GdkModifierIntent  intent)
+{
+  switch (intent)
+    {
+    case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
+      return GDK_MOD2_MASK;
+
+    case GDK_MODIFIER_INTENT_CONTEXT_MENU:
+      return GDK_CONTROL_MASK;
+
+    case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
+      return GDK_SHIFT_MASK;
+
+    case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
+      return GDK_MOD2_MASK;
+
+    case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
+      return GDK_MOD2_MASK | GDK_CONTROL_MASK;
+
+    default:
+      g_return_val_if_reached (0);
+    }
+}
+
 /* What sort of key event is this? Returns one of
  * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
  */
@@ -835,4 +861,5 @@ gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
   keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
   keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
   keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;
+  keymap_class->get_modifier_mask = gdk_quartz_keymap_get_modifier_mask;
 }
index f90e3b3099c6f7a4d932553e80b5cf721da844b7..3e9e1d5e762609d0ce514acd890576405b27f38c 100644 (file)
@@ -14542,3 +14542,31 @@ gtk_widget_get_style_context (GtkWidget *widget)
 
   return widget->priv->context;
 }
+
+/**
+ * gtk_widget_get_modifier_mask:
+ * @widget: a #GtkWidget
+ * @intent: the use case for the modifier mask
+ *
+ * Returns the modifier mask the @widget's windowing system backend
+ * uses for a particular purpose.
+ *
+ * See gdk_keymap_get_modifier_mask().
+ *
+ * Returns: the modifier mask used for @intent.
+ *
+ * Since: 3.4
+ **/
+GdkModifierType
+gtk_widget_get_modifier_mask (GtkWidget         *widget,
+                              GdkModifierIntent  intent)
+{
+  GdkDisplay *display;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
+
+  display = gtk_widget_get_display (widget);
+
+  return gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
+                                       intent);
+}
index ead01ed4d1d5ec702012e79d6497f0f7ee7ee3d8..2da9ae3623c985228de601b5e34020749d91ba8b 100644 (file)
@@ -949,6 +949,9 @@ GtkStyleContext * gtk_widget_get_style_context (GtkWidget *widget);
 
 GtkWidgetPath *   gtk_widget_get_path (GtkWidget *widget);
 
+GdkModifierType   gtk_widget_get_modifier_mask (GtkWidget         *widget,
+                                                GdkModifierIntent  intent);
+
 
 G_END_DECLS